package be.nepherte.movmanager.domain;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.jdo.annotations.Element;
import javax.jdo.annotations.Extension;
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.Order;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;

import be.nepherte.movmanager.client.exceptions.MovieAlreadyExistsException;

import com.google.appengine.api.datastore.Key;

/**
 * This class represents a movie collection. Each movie collection contains a
 * list of {@link Movie movies} and each collection is linked to 1 specific user.
 * 
 * <p>
 * Copyright © 2010 Bart Verhoeven
 * </p>
 * 
 * <p>
 * This file is part of MovManager.
 * </p>
 * 
 * <p>
 * MovManager is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 * </p>
 * 
 * <p>
 * MovManager is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 * </p>
 * 
 * <p>
 * You should have received a copy of the GNU General Public License along with
 * MovManager. If not, see http://www.gnu.org/licenses/.
 * </p>
 * 
 * @author Bart Verhoeven
 * @version 0.1
 */
@PersistenceCapable(identityType = IdentityType.APPLICATION, detachable = "true")
public class MovieCollection implements Serializable {
	private static final long serialVersionUID = 1L;
	/**Unique key identifier for this movie collection used for data storage.*/
	@PrimaryKey
	@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
	private Key key;
	/**List of movies that belong to this movie collection.*/
	@Persistent(mappedBy = "movieCollection")
	@Element(dependent = "true")
	@Order(extensions = @Extension(vendorName="datanucleus", key="list-ordering", value="title asc"))
	private List<Movie> movieCollection = new ArrayList<Movie>();
	/**The user's id this movie collection belongs to.*/
	@Persistent
	private String userId;
	
	
	/**
	 * Default empty constructor required by the Google RPC protocol.
	 */
	public MovieCollection() {}
	
	/**
	 * Constructor for this movie collection.
	 * 
	 * @param	userId
	 * 			the user's id this collection belongs to
	 */
	public MovieCollection(String userId) {
		setUserId(userId);
	}

	/**
	 * Retrieves the primary key for this object.
	 * 
	 * @return	key
	 */
	public Key getKey() {
		return key;
	}
	
	/**
	 * Sets the unique identifier for this movie collection. Note that the key is
	 * automatically generated and assigned upon storage in the database. This
	 * method is only here to reconstruct this object upon retrieval from the
	 * database and should not be used.
	 * 
	 * @param	key
	 *          the new unique identifier belonging to this movie collection
	 */
	public void setKey(Key key) {
		this.key = key;
	}
	
	/**
	 * Retrieves the id of the user this movie collection to.
	 * 
	 * @return	userId
	 */
	public String getUserId() {
		return userId;
	}
	
	/**
	 * Sets the id of the user this movie collection belongs to. This
	 * method is only here to reconstruct this object upon retrieval from
	 * the database.
	 * 
	 * 
	 * @param	id
	 * 			the new id of the user this movie collection belongs to
	 */
	public void setUserId(String id) {
		this.userId = id;
	}
	
	/**
	 * Retrieves a list with all the movies in this movie collection.
	 * 
	 * @return	movieCollection
	 */
	public List<Movie> getMovieCollection() {
		return movieCollection;
	}
	
	/**
	 * Sets the list of movies in this movie collection.
	 * 
	 * @param 	collection
	 * 			the new list of movies for this movie collection
	 */
	public void setMovieCollection(List<Movie> collection) {
		this.movieCollection = collection;
	}
	
	/**
	 * Adds given movie to this movie collection.
	 * 
	 * @param 	movie
	 * 			the movie to be added to this movie collection
	 * @throws	MovieAlreadyExistsException
	 * 			the movie already exists in this movie collection
	 */
	public void addMovie(Movie movie) throws MovieAlreadyExistsException {
		if (movie == null)
			return;
		
		for (Movie m: movieCollection)
			if (m.getTitle().equals(movie.getTitle()))
				throw new MovieAlreadyExistsException("The movie " + movie.getTitle() + " already exists.");
		
		movieCollection.add(movie);
	}
	
	/**
	 * Removes given movie from this movie collection.
	 * 
	 * @param	movie
	 * 			the movie to be removed from this movie collection
	 */
	public void removeMovie(Movie movie) {
		movieCollection.remove(movie);
	}
}
